package com.qijian.flowable.common.listener;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.qijian.common.enums.FlowableCommonEnum;
import com.qijian.common.enums.FlowableKeyEnum;
import com.qijian.common.utils.CommonUtil;
import com.qijian.common.utils.DateUtils;
import com.qijian.common.utils.StringUtils;
import com.qijian.flowable.constant.FlowableConstant;
import com.qijian.flowable.mapper.FlowableCommonMapper;
import com.qijian.flowable.service.IFlowableRecordService;
import com.qijian.flowable.service.IProcessDefinitionService;
import com.qijian.flowable.util.SpringContextUtils;
import com.qijian.tool.domain.Msg;
import com.qijian.tool.service.IMsgService;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.cfg.TransactionState;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.delegate.event.impl.FlowableEntityWithVariablesEventImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.task.Comment;
import org.flowable.idm.api.User;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 全局监听器，判断流程是不是运行到了最后一个EndEvent
 *
 * @author qijian
 */
@Component
public class ProcessEndListener implements FlowableEventListener {

    @Override
    public void onEvent(FlowableEvent event) {
        // 当前节点任务实体,
        ExecutionEntity ee;
        try {
            ee = (ExecutionEntity) ((FlowableEntityEventImpl) event).getEntity();
        } catch (Exception e) {
            ee = (ExecutionEntity) ((FlowableEntityWithVariablesEventImpl) event).getEntity();
        }
        // 流程完成，修改状态
        Map<String, Object> variables = ee.getVariables();
        TaskService taskService = SpringContextUtils.getBean(TaskService.class);
        List<Comment> datas = taskService.getProcessInstanceComments(ee.getProcessInstanceId());
        String nickName = null;
        if (CollectionUtil.isNotEmpty(datas) && StringUtils.isNotBlank(datas.get(0).getUserId())) {
            FlowableCommonMapper flowableCommonMapper = SpringContextUtils.getBean(FlowableCommonMapper.class);
            User user = flowableCommonMapper.selectUserById(Long.valueOf(datas.get(0).getUserId()));
            if (ObjectUtil.isNotNull(user)) {
                nickName = user.getFirstName();
            }
        }

        if (CollectionUtil.isEmpty(datas) || !FlowableConstant.ZZ.equals(datas.get(0).getType())) {
            IFlowableRecordService flowableRecordService = SpringContextUtils.getBean(IFlowableRecordService.class);
            flowableRecordService.updateByProcessIntaneId(ee.getProcessInstanceId(), CollectionUtil.isNotEmpty(variables) ? (String) variables.get("processInstanceFormData") : null, nickName, Long.valueOf(datas.get(0).getUserId()));
        }
        String createTime = variables.get("createTime")== null ? "" : variables.get("createTime").toString();
        //发送消息（新增功能以后通过监听器发送消息）
        //获取流程实列（安全事故，安全奖励，安全惩罚）
        IProcessDefinitionService processDefinitionService = SpringContextUtils.getBean(IProcessDefinitionService.class);
        ProcessDefinition processDefinition = processDefinitionService.getProcessDefinitionById(ee.getProcessDefinitionId());
        if (processDefinition != null) {
            if (FlowableConstant.FLOWABLE_MSG_SENDER.contains(processDefinition.getName())) {
                IMsgService msgService = SpringContextUtils.getBean(IMsgService.class);

                String sourceId = null;
                for (Map.Entry entry : variables.entrySet()) {
                    if (entry.getKey().toString().indexOf("input_") > -1) {
                        sourceId = entry.getValue().toString();
                        break;
                    }
                }

                List<Msg> msgs = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(datas)){
                    Comment component = datas.get(0);
                    //退回消息到发送人，事故当事人
                    if (FlowableConstant.ZZ.equals(component.getType()) || FlowableConstant.CC.equals(component.getType())) {
                        if (variables.get("title") !=null) {
                            List<Long> userList = new ArrayList<>();
                            String cc = (String)variables.get("cc");
                            if (StringUtils.isNotEmpty(cc)){
                                List<String> ccList = Arrays.asList(cc.split(","));
                                if (CollectionUtils.isNotEmpty(ccList)) {
                                    userList.addAll(ccList.stream().map(e->Long.parseLong(e)).collect(Collectors.toList()));
                                }
                                Set<Long> users = new HashSet(userList);
                                for (Long u : users) {
                                    Msg msg = new Msg();
                                    msg.setSourceId(sourceId);
                                    msg.setSourceType(processDefinition.getKey());
                                    msg.setUserId(u);
                                    msg.setTitle("(抄送)"+variables.get("title1").toString());
                                    msg.setCreateBy("admin");
                                    msg.setContent("您收到一条抄送" + processDefinition.getName() + "消息");
                                    Object mainFlowType = variables.get("mainFlowType");
                                    if(Objects.nonNull(mainFlowType)){
                                        if(StrUtil.equals(String.valueOf(mainFlowType), FlowableCommonEnum.flow_fin_finance_dispatch.getValue())){
                                            Object flowSourceId = variables.get("sourceId");
                                            msg.setUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey()+"_t")+ CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t")) +"id="+flowSourceId);
                                        }else if(StrUtil.equals(String.valueOf(mainFlowType), FlowableCommonEnum.flow_process_craft_dispatch.getValue())){
                                            Object flowSourceId = variables.get("sourceId");
                                            msg.setUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t") + CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t")) + "id=" + flowSourceId);
                                        } else if (StrUtil.equals(String.valueOf(mainFlowType), FlowableCommonEnum.flow_process_performance.getValue())) {
                                            Object flowSourceId = variables.get("sourceId");
                                            msg.setUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t") + CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t")) + "id=" + flowSourceId);
                                        } else if (StrUtil.equals(String.valueOf(mainFlowType), FlowableCommonEnum.flow_quality_craft_dispatch.getValue())) {
                                            Object flowSourceId = variables.get("sourceId");
                                            msg.setUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t") + CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t")) + "id=" + flowSourceId);
                                        } else {
                                            msg.setUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t") + CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t")) + "id=" + sourceId);
                                        }
                                    }else{
                                        msg.setUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey()+"_t")+ CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(processDefinition.getKey() + "_t")) +"id="+sourceId);
                                    }
                                    if(StringUtils.isNotEmpty(createTime)) {
                                        msg.setOriginCreateDateTime(DateUtils.strToDate(createTime, DatePattern.NORM_DATETIME_PATTERN));
                                    }
                                    msg.setCreateByName(variables.get("userName").toString());
                                    msg.setTaskId(null);
                                    msg.setProcessInstanceId(ee.getProcessInstanceId());
                                    msgs.add(msg);
                                }
                            }

                        }
                    }
                }
                if (CollectionUtil.isNotEmpty(msgs)) {
                    msgService.saveBatch(msgs,true,true);
                }

            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return true;
    }

    @Override
    public String getOnTransaction() {
        //事务提交后触发
        return TransactionState.COMMITTED.name();
    }
}
